package com.ruoyi.eqmonitor.controller;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import breeze.framework.string.Str;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.datasource.annotation.Monitor;
import com.ruoyi.eqmonitor.dispose.service.IotService;
import com.ruoyi.eqmonitor.domain.*;
import com.ruoyi.eqmonitor.dtos.*;
import com.ruoyi.eqmonitor.service.IOptDeviceAlarmService;
import com.ruoyi.eqmonitor.service.IOptDeviceMonitorAnalyseDataService;
import com.ruoyi.eqmonitor.service.IOptDeviceMonitorLastDataService;
import com.ruoyi.eqmonitor.service.IOptDeviceService;
import com.ruoyi.eqmonitor.utils.Constant;
import com.ruoyi.eqmonitor.utils.IotUtils;
import io.swagger.annotations.ApiOperation;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;

import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;

import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.security.utils.SecurityUtils;

import com.ruoyi.common.core.web.page.TableDataInfo;

/**
 * 设备管理
 * @author ruoyi
 * @date 2022-11-25
 */
@Slf4j
@RestController
@RequestMapping("/device")
public class OptDeviceController extends BaseController{
    @Autowired
    private IotService iotService;
    @Autowired
    private IOptDeviceService optDeviceService;
    @Autowired
    private IOptDeviceAlarmService optDeviceAlarmService;
    @Autowired
    private IOptDeviceMonitorLastDataService optDeviceMonitorLastDataService;

    @Autowired
    private IOptDeviceMonitorAnalyseDataService optDeviceMonitorAnalyseDataService;
    /*
    手动执行定时任务
    @GetMapping("runTask")
    public AjaxResult runTask(){
        optDeviceMonitorAnalyseDataService.analyseDailyAccumulation(new Date());
        return AjaxResult.success();
    }*/
    /**
     * 刷新设备管理缓存
     */
    @ApiOperation("刷新设备管理缓存")
    @GetMapping("/refreshCache")
    public AjaxResult refreshCache(){
        return AjaxResult.success(optDeviceService.refreshCache());
    }

    /**
     * 查询设备管理列表
     */
    @ApiOperation("查询设备管理列表")
    @GetMapping("/list")
    public TableDataInfo<?> list(OptDeviceDto optDevice){
        startPage();
        List<OptDeviceDto> list = optDeviceService.selectOptDeviceList(optDevice);
        return getDataTable(list);
    }
    @ApiOperation("查询设备管理列表")
    @GetMapping("/listForDln")
    public TableDataInfo<?> listForDln(OptDeviceDto optDevice){

        Date currentDate = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currentDate);
        calendar.add(Calendar.DAY_OF_MONTH, -7);
        Date newDate = calendar.getTime();

        startPage();
        List<OptDeviceDto> list = optDeviceService.selectOptDeviceList(optDevice);
        list.forEach(optDeviceDto -> {
            optDeviceDto.setName(optDeviceDto.getDeviceName());
            optDeviceDto.setDeviceName(null);
            optDeviceDto.setNum(optDeviceDto.getDeviceCode());
            AlarmSearchInput optDeviceAlarm = new AlarmSearchInput();
            optDeviceAlarm.setStartTime(newDate);
            optDeviceAlarm.setEndTime(currentDate);
            optDeviceAlarm.setPersistentStatus(0);
            optDeviceAlarm.setDeviceCode(optDeviceDto.getDeviceCode());
            LambdaQueryWrapper<OptDeviceAlarm> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(OptDeviceAlarm::getDeviceCode, optDeviceDto.getDeviceCode())
                    .eq(OptDeviceAlarm::getPersistentStatus, 0)
                    .ge(OptDeviceAlarm::getLastAlarmTime,optDeviceAlarm.getStartTime())
                    .lt(OptDeviceAlarm::getLastAlarmTime,optDeviceAlarm.getEndTime());
            List<OptDeviceAlarm> alarms = optDeviceAlarmService.list(queryWrapper);
            optDeviceDto.setIsAlarm(!alarms.isEmpty());
        });
        return getDataTable(list);
    }
    @ApiOperation("查询点位列表")
    @GetMapping("/pointList")
    public AjaxResult pointList(){
        List<OptPointDto> list = optDeviceService.selectOptPointList();
        List<OptPointDto> listResult = new ArrayList<>();
        List<String> siteList = new ArrayList<>();
        LocalDateTime startTime = LocalDateTime.now().minusDays(2);
        LocalDateTime endTime = LocalDateTime.now();
        list.forEach(optPointDto -> {
            if(!siteList.contains(optPointDto.getSiteId())){
                siteList.add(optPointDto.getSiteId());
                int alarmCount = optDeviceAlarmService.countAlarm(optPointDto.getSiteId(),startTime,endTime);
                if(alarmCount>0){
                    optPointDto.setAlarm(true);
                }else {
                    optPointDto.setAlarm(false);
                }
                listResult.add(optPointDto);
            }
        });
        return success(listResult);
    }
    @ApiOperation("设备在线/离线统计")
    @GetMapping("/onOffLineCount")
    public AjaxResult onOffLineCount(@RequestParam(required = false) String sensorType){
        JSONObject result = new JSONObject();
        OnOffLineDto dtoOnline = new OnOffLineDto();
        dtoOnline.setState(1);
        dtoOnline.setSensorType(sensorType);
        int onLineSum = optDeviceService.selectOnOffLineBySensorType(dtoOnline).size();
        result.put("onlineSum", onLineSum);
        OnOffLineDto dtoOutline = new OnOffLineDto();
        dtoOutline.setState(2);
        dtoOutline.setSensorType(sensorType);
        int outLineSum = optDeviceService.selectOnOffLineBySensorType(dtoOutline).size();
        result.put("sum", onLineSum+outLineSum);
        JSONObject onlineMap = new JSONObject();
        if("jg".equals(sensorType)){
            onlineMap.put("jgData", optDeviceService.getCountJson("jg"));
        }else if ("yw".equals(sensorType)){
            onlineMap.put("ywData", optDeviceService.getCountJson("yw"));
        }else if ("ll".equals(sensorType)){
            onlineMap.put("llData", optDeviceService.getCountJson("ll"));
        }else {
            onlineMap.put("jgData", optDeviceService.getCountJson("jg"));
            onlineMap.put("ywData", optDeviceService.getCountJson("yw"));
            onlineMap.put("llData", optDeviceService.getCountJson("ll"));
        }
        result.put("onlineMap", onlineMap);
        return AjaxResult.success(result);
    }
    @PostMapping("latestDataBySncode")
    public AjaxResult latestDataBySncode(@RequestBody JSONObject params){
        String sensorType = params.getString("sensorType");
        String snCode = params.getString("snCode");
        /*String code = "";
        String code2 = "";
        if ("yw".equals(sensorType)) {
            code = Constant.MonitorInfo.M_0x05D1.getCode();
        }else if("ll".equals(sensorType)){
            code = Constant.MonitorInfo.C_CC0001.getCode();
            code2 = Constant.MonitorInfo.M_0x0592.getCode();
        }else {
            return  AjaxResult.error("参数异常");
        }*/

        JSONObject object = new JSONObject();
        object.put("snCode",snCode);
        if ("yw".equals(sensorType)) {
            //MonitorInfo.M_0x05D1, 液位高度
            //MonitorInfo.M_0x0593, 流速
            //MonitorInfo.M_0x0502, 温度
            //MonitorInfo.M_0x0592, 瞬时流量
            //MonitorInfo.M_0x0590  正向累积流量
            OptDeviceMonitorLastData optDeviceMonitorLastData1 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x05D1.getCode(),snCode);
            double codeValue1 = BigDecimal.valueOf(optDeviceMonitorLastData1==null?0:optDeviceMonitorLastData1.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("level", codeValue1);
            OptDeviceMonitorLastData optDeviceMonitorLastData2 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x0593.getCode(),snCode);
            double codeValue2 = BigDecimal.valueOf(optDeviceMonitorLastData2==null?0:optDeviceMonitorLastData2.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("speed", codeValue2);
            OptDeviceMonitorLastData optDeviceMonitorLastData3 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x0502.getCode(), snCode);
            double codeValue3 = BigDecimal.valueOf(optDeviceMonitorLastData3==null?0:optDeviceMonitorLastData3.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("temperature", codeValue3);
            OptDeviceMonitorLastData optDeviceMonitorLastData4 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x0592.getCode(), snCode);
            double codeValue4 = BigDecimal.valueOf(optDeviceMonitorLastData4==null?0:optDeviceMonitorLastData4.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("instantFlow", codeValue4);
            OptDeviceMonitorLastData optDeviceMonitorLastData5 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x0590.getCode(), snCode);
            double codeValue5 = BigDecimal.valueOf(optDeviceMonitorLastData5==null?0:optDeviceMonitorLastData5.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("totalFlow", codeValue5);

        }else if ("sz".equals(sensorType)) {
//            Constant.MonitorInfo.M_0x0502,  温度
//            Constant.MonitorInfo.M_0x0520,  浊度
//            Constant.MonitorInfo.M_0x0501,  设备实时电压
//            Constant.MonitorInfo.M_0x0528,  氨氮
//            Constant.MonitorInfo.M_0x0527   COD
            OptDeviceMonitorLastData optDeviceMonitorLastData1 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x0502.getCode(), snCode);
            double codeValue1 = BigDecimal.valueOf(optDeviceMonitorLastData1==null?0:optDeviceMonitorLastData1.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("temperature", codeValue1);
            OptDeviceMonitorLastData optDeviceMonitorLastData2 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x0520.getCode(), snCode);
            double codeValue2 = BigDecimal.valueOf(optDeviceMonitorLastData2==null?0:optDeviceMonitorLastData2.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("zd", codeValue2);
            OptDeviceMonitorLastData optDeviceMonitorLastData3 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x0501.getCode(), snCode);
            double codeValue3 = BigDecimal.valueOf(optDeviceMonitorLastData3==null?0:optDeviceMonitorLastData3.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("voltage", codeValue3);
            OptDeviceMonitorLastData optDeviceMonitorLastData4 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x0528.getCode(), snCode);
            double codeValue4 = BigDecimal.valueOf(optDeviceMonitorLastData4==null?0:optDeviceMonitorLastData4.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("an", codeValue4);
            OptDeviceMonitorLastData optDeviceMonitorLastData5 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x0527.getCode(), snCode);
            double codeValue5 = BigDecimal.valueOf(optDeviceMonitorLastData5==null?0:optDeviceMonitorLastData5.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("cod", codeValue5);

        }else if ("yl".equals(sensorType)) {
//        Constant.MonitorInfo.M_0x0501,  电压
//        Constant.MonitorInfo.M_0x0566,  24小时雨量
//        Constant.MonitorInfo.M_0x0567,  当天降雨量
//        Constant.MonitorInfo.M_0x0568,  瞬时降雨量
//        Constant.MonitorInfo.M_0x0569,  总降雨量
//        Constant.MonitorInfo.M_0x056A,  小时降雨量
//        Constant.MonitorInfo.M_0x056B,  上小时降雨量
//        Constant.MonitorInfo.M_0x6500   电池电量
            OptDeviceMonitorLastData optDeviceMonitorLastData1 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x0501.getCode(), snCode);
            double codeValue1 = BigDecimal.valueOf(optDeviceMonitorLastData1==null?0:optDeviceMonitorLastData1.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("voltage", codeValue1);
            OptDeviceMonitorLastData optDeviceMonitorLastData2 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x0566.getCode(), snCode);
            double codeValue2 = BigDecimal.valueOf(optDeviceMonitorLastData2==null?0:optDeviceMonitorLastData2.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("hour24", codeValue2);
            OptDeviceMonitorLastData optDeviceMonitorLastData3 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x0567.getCode(), snCode);
            double codeValue3 = BigDecimal.valueOf(optDeviceMonitorLastData3==null?0:optDeviceMonitorLastData3.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("today", codeValue3);
            OptDeviceMonitorLastData optDeviceMonitorLastData4 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x0568.getCode(), snCode);
            double codeValue4 = BigDecimal.valueOf(optDeviceMonitorLastData4==null?0:optDeviceMonitorLastData4.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("instant", codeValue4);
            OptDeviceMonitorLastData optDeviceMonitorLastData5 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x0569.getCode(), snCode);
            double codeValue5 = BigDecimal.valueOf(optDeviceMonitorLastData5==null?0:optDeviceMonitorLastData5.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("sum", codeValue5);
            OptDeviceMonitorLastData optDeviceMonitorLastData6 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x056A.getCode(), snCode);
            double codeValue6 = BigDecimal.valueOf(optDeviceMonitorLastData6==null?0:optDeviceMonitorLastData6.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("hour", codeValue6);
            OptDeviceMonitorLastData optDeviceMonitorLastData7 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x056B.getCode(), snCode);
            double codeValue7 = BigDecimal.valueOf(optDeviceMonitorLastData7==null?0:optDeviceMonitorLastData7.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("lastHour", codeValue7);
            OptDeviceMonitorLastData optDeviceMonitorLastData8 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x6500.getCode(), snCode);
            double codeValue8 = BigDecimal.valueOf(optDeviceMonitorLastData8==null?0:optDeviceMonitorLastData8.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("eleQuality", codeValue8);

        } else if ("dl".equals(sensorType)) {
   //         Constant.MonitorInfo.M_0x0501,  电压
    //                Constant.MonitorInfo.M_0x05D1, 液位高度
    //                Constant.MonitorInfo.M_0x6500 电池电量

            OptDeviceMonitorLastData optDeviceMonitorLastData1 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x0501.getCode(), snCode);
            double codeValue1 = BigDecimal.valueOf(optDeviceMonitorLastData1==null?0:optDeviceMonitorLastData1.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("voltage", codeValue1);
            OptDeviceMonitorLastData optDeviceMonitorLastData2 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x05D1.getCode(),snCode);
            double codeValue2 = BigDecimal.valueOf(optDeviceMonitorLastData2==null?0:optDeviceMonitorLastData2.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("level", codeValue1);
            OptDeviceMonitorLastData optDeviceMonitorLastData8 = optDeviceMonitorLastDataService.getBySncodeAndCode(Constant.MonitorInfo.M_0x6500.getCode(), snCode);
            double codeValue8 = BigDecimal.valueOf(optDeviceMonitorLastData8==null?0:optDeviceMonitorLastData8.getCodeValue()).setScale(2, RoundingMode.HALF_UP).doubleValue();
            object.put("eleQuality", codeValue8);
        }
        return AjaxResult.success(object);
    }

    @ApiOperation("按点位id查最新数据")
    @GetMapping("latestDataBySiteId")
    public AjaxResult latestDataBySiteId(@RequestParam String siteId,@RequestParam int weight){
        List<String> sensors = new ArrayList<>();
        List<String> sensorCodes = new ArrayList<>();
        switch (weight){
            case 1:
                sensors.add("jg");
                //井盖倾角
                sensorCodes.add("0x06B0");
                break;
            case 2:
                sensors.add("yw");
                //0x05D1
                sensorCodes.add("0x05D1");
                break;
            case 3:
                sensors.add("jg");
                sensors.add("yw");
                //井盖倾角
                sensorCodes.add("0x06B0");
                //0x05D1
                sensorCodes.add("0x05D1");
                break;
            case 4:
                sensors.add("ll");
                //正向累计流量
                sensorCodes.add("0x0590");
                //瞬时流量
                sensorCodes.add("0x0592");
                //流速
                sensorCodes.add("0x0593");
                break;
            case 5:
                sensors.add("jg");
                sensors.add("ll");
                //井盖倾角
                sensorCodes.add("0x06B0");
                //正向累计流量
                sensorCodes.add("0x0590");
                //瞬时流量
                sensorCodes.add("0x0592");
                //流速
                sensorCodes.add("0x0593");
                break;
            case 6:
                sensors.add("yw");
                sensors.add("ll");
                //0x05D1
                sensorCodes.add("0x05D1");
                //正向累计流量
                sensorCodes.add("0x0590");
                //瞬时流量
                sensorCodes.add("0x0592");
                //流速
                sensorCodes.add("0x0593");
                break;
            case 7:
                sensors.add("jg");
                sensors.add("yw");
                sensors.add("ll");
                //井盖倾角
                sensorCodes.add("0x06B0");
                //0x05D1
                sensorCodes.add("0x05D1");
                //正向累计流量
                sensorCodes.add("0x0590");
                //瞬时流量
                sensorCodes.add("0x0592");
                //流速
                sensorCodes.add("0x0593");
                break;
            default:
                break;
        }
        List<OptDeviceDto> list = optDeviceService.selectOptDeviceListBySiteId(siteId,sensors);
        //处理雷达
        if(weight!=1 && weight!=7){
            list.add(optDeviceService.getDeviceByCode("587BCL"));
        }
        JSONArray array = new JSONArray();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        list.forEach(optDeviceDto -> {
            JSONArray data = new JSONArray();
            JSONObject object = new JSONObject();
            object.put("deviceCode",optDeviceDto.getDeviceCode());
            object.put("deviceName",optDeviceDto.getDeviceNameVice());
            sensorCodes.forEach(sensorCode->{
                OptDeviceMonitorLastData optDeviceMonitorLastData = optDeviceMonitorLastDataService.getBySncodeAndCode(sensorCode,optDeviceDto.getDeviceCode());
                JSONObject innerData = new JSONObject();
                if(optDeviceMonitorLastData!=null){
                    double codeValue = BigDecimal.valueOf(optDeviceMonitorLastData.getCodeValue()).setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
                    if("井盖倾角".equals(Constant.MonitorInfo.getInfoByCode(sensorCode).getName())){
                        innerData.put("name","井盖状态");
                        innerData.put("unit","/");
                        innerData.put("value",codeValue);
                        innerData.put("status",codeValue>30?"开启":"关闭");
                        innerData.put("time",sdf.format(optDeviceMonitorLastData.getMonitorTime()));
                    }else if("瞬时流量".equals(Constant.MonitorInfo.getInfoByCode(sensorCode).getName())){
                        innerData.put("name",Constant.MonitorInfo.getInfoByCode(sensorCode).getName());
                        innerData.put("unit",Constant.MonitorInfo.getInfoByCode(sensorCode).getUnit());
                        innerData.put("value",codeValue);
                        innerData.put("time",sdf.format(optDeviceMonitorLastData.getMonitorTime()));
                        if(codeValue<0.5){
                            innerData.put("status", "流速过缓");
                        }else {
                            innerData.put("status", "正常");
                        }
                    }else if("正向累积流量".equals(Constant.MonitorInfo.getInfoByCode(sensorCode).getName())){
                        innerData.put("name","日累积流量");
                        innerData.put("unit",Constant.MonitorInfo.getInfoByCode(sensorCode).getUnit());
                        // 昨天的日期
                        String yesterday = DateUtil.formatDate(DateUtil.offsetDay(new Date(), -1));
                        // 查昨日累计流量
                        LambdaQueryWrapper<OptDeviceMonitorAnalyseData> llWrapper = Wrappers.<OptDeviceMonitorAnalyseData>lambdaQuery()
                                .eq(OptDeviceMonitorAnalyseData::getDeviceCode, optDeviceDto.getDeviceCode())
                                .eq(OptDeviceMonitorAnalyseData::getCode, Constant.MonitorInfo.C_CC0001.getCode())
                                .eq(OptDeviceMonitorAnalyseData::getMonitorTime, yesterday)
                                .orderByDesc(OptDeviceMonitorAnalyseData::getMonitorTime)
                                .last("LIMIT 1");
                        OptDeviceMonitorAnalyseData llOne = optDeviceMonitorAnalyseDataService.getOne(llWrapper);
                        if (llOne == null) {
                            log.error("昨日流量为空");
                            innerData.put("value","");
                        }else {
                            innerData.put("value",llOne.getCodeValue()+"");
                        }
                        innerData.put("time",sdf.format(optDeviceMonitorLastData.getMonitorTime()));
                    } else if("液位高度".equals(Constant.MonitorInfo.getInfoByCode(sensorCode).getName())){
                        innerData.put("name", Constant.MonitorInfo.getInfoByCode(sensorCode).getName());
                        innerData.put("unit",Constant.MonitorInfo.getInfoByCode(sensorCode).getUnit());
                        innerData.put("value",codeValue);
                        innerData.put("status","正常");
                        innerData.put("time",sdf.format(optDeviceMonitorLastData.getMonitorTime()));
                    } else  {
                        innerData.put("name",Constant.MonitorInfo.getInfoByCode(sensorCode).getName());
                        innerData.put("unit",Constant.MonitorInfo.getInfoByCode(sensorCode).getUnit());
                        innerData.put("value",codeValue);
                        innerData.put("time",sdf.format(optDeviceMonitorLastData.getMonitorTime()));
                    }
                    data.add(innerData);
                }
            });
            object.put("data", data);
            array.add(object);
        });
        return success(array);
    }
    @RequestMapping("statistic")
    public AjaxResult statistic(@RequestParam String snCode){
        OptDeviceDto optDevice = optDeviceService.getDeviceByCode(snCode);
        String deviceType = optDevice.getDeviceType();
        System.err.println(deviceType);
        LocalDateTime startTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DecimalFormat decimalFormat = new DecimalFormat("0.00");
        JSONArray chartData = new JSONArray();
        //流量液位一体
        if("SY800-L-Y0".equals(deviceType)){
            //液位
            JSONArray times = new JSONArray();
            JSONArray datas = new JSONArray();
            JSONObject object = new JSONObject();
            String unit = "m";
            String attribute = "液位";
            IntStream.range(0,10).forEach(i->{
                LocalDateTime start = startTime.minusDays(9-i);
                LocalDateTime end = endTime.minusDays(9-i);
                times.add(dateTimeFormatter.format(start));
                //液位高度
                Double avg = iotService.avgBySnAndCode(snCode,"0x05D1",start,end);
                datas.add(avg==null?0:Double.parseDouble(decimalFormat.format(avg)));
            });
            object.put("times", times);
            object.put("datas", datas);
            object.put("unit", unit);
            object.put("attribute", attribute);
            chartData.add(object);

            //流量
            //正向累积流量
            JSONArray times2 = new JSONArray();
            JSONArray datas2 = new JSONArray();
            JSONObject object2 = new JSONObject();
            String unit2 = "m³";
            String attribute2 = "正向累积流量";
            IntStream.range(0,10).forEach(i->{
                LocalDateTime start = startTime.minusDays(9-i);
                LocalDateTime end = endTime.minusDays(9-i);
                times2.add(dateTimeFormatter.format(start));
                Double max = iotService.maxBySnAndCode(snCode,"0x0590",start,end);
                datas2.add(max==null?0:Double.parseDouble(decimalFormat.format(max)));
            });
            object2.put("times", times2);
            object2.put("datas", datas2);
            object2.put("unit", unit2);
            object2.put("attribute", attribute2);
            chartData.add(object2);
        }else if("SR500-L-Y0-SNY".equals(deviceType)){
            //水质--cod
            JSONArray times = new JSONArray();
            JSONArray datas = new JSONArray();
            JSONObject object = new JSONObject();
            String unit = "mg/L";
            String attribute = "cod";
            IntStream.range(0,10).forEach(i->{
                LocalDateTime start = startTime.minusDays(9-i);
                LocalDateTime end = endTime.minusDays(9-i);
                times.add(dateTimeFormatter.format(start));
                //液位高度
                Double avg = iotService.avgBySnAndCode(snCode,"0x0527",start,end);
                datas.add(avg==null?0:Double.parseDouble(decimalFormat.format(avg)));
            });
            object.put("times", times);
            object.put("datas", datas);
            object.put("unit", unit);
            object.put("attribute", attribute);
            chartData.add(object);
            //浊度
            JSONArray times2 = new JSONArray();
            JSONArray datas2 = new JSONArray();
            JSONObject object2 = new JSONObject();
            String unit2 = "NTU";
            String attribute2 = "浊度";
            IntStream.range(0,10).forEach(i->{
                LocalDateTime start = startTime.minusDays(9-i);
                LocalDateTime end = endTime.minusDays(9-i);
                times2.add(dateTimeFormatter.format(start));
                Double avg = iotService.avgBySnAndCode(snCode,"0x0520",start,end);
                datas2.add(avg==null?0:Double.parseDouble(decimalFormat.format(avg)));
            });
            object2.put("times", times2);
            object2.put("datas", datas2);
            object2.put("unit", unit2);
            object2.put("attribute", attribute2);
            chartData.add(object2);
            //氨氮
            JSONArray times3 = new JSONArray();
            JSONArray datas3 = new JSONArray();
            JSONObject object3 = new JSONObject();
            String unit3 = "mg/L";
            String attribute3 = "氨氮";
            IntStream.range(0,10).forEach(i->{
                LocalDateTime start = startTime.minusDays(9-i);
                LocalDateTime end = endTime.minusDays(9-i);
                times3.add(dateTimeFormatter.format(start));
                Double avg = iotService.avgBySnAndCode(snCode,"0x0528",start,end);
                datas3.add(avg==null?0:Double.parseDouble(decimalFormat.format(avg)));
            });
            object3.put("times", times3);
            object3.put("datas", datas3);
            object3.put("unit", unit3);
            object3.put("attribute", attribute3);
            chartData.add(object3);
        }else if("SR500-N-D2-LD".equals(deviceType)){
            //液位
            JSONArray times = new JSONArray();
            JSONArray datas = new JSONArray();
            JSONObject object = new JSONObject();
            String unit = "m";
            String attribute = "液位";
            IntStream.range(0,10).forEach(i->{
                LocalDateTime start = startTime.minusDays(9-i);
                LocalDateTime end = endTime.minusDays(9-i);
                times.add(dateTimeFormatter.format(start));
                //液位高度
                Double avg = iotService.avgBySnAndCode(snCode,"0x05D1",start,end);
                datas.add(avg==null?0:Double.parseDouble(decimalFormat.format(avg)));
            });
            object.put("times", times);
            object.put("datas", datas);
            object.put("unit", unit);
            object.put("attribute", attribute);
            chartData.add(object);

        }


        return AjaxResult.success(chartData);
    }

    @RequestMapping("statistic2")
    public AjaxResult statistic2(@RequestParam String snCode){
        OptDeviceDto optDevice = optDeviceService.getDeviceByCode(snCode);
        String deviceType = optDevice.getDeviceType();
        LocalDateTime startTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DecimalFormat decimalFormat = new DecimalFormat("0.00");
        JSONArray chartData = new JSONArray();
        if("SR500-L-Y0-LD".equals(deviceType) || "587BCL".equals(snCode)){
            //瞬时流量
            JSONArray times = new JSONArray();
            JSONArray datas = new JSONArray();
            JSONObject object = new JSONObject();
            String unit = "m³/s";
            String attribute = "瞬时流量";
            IntStream.range(0,10).forEach(i->{
                log.info("瞬时流量:{}", i);
                LocalDateTime start = startTime.minusDays(9-i);
                LocalDateTime end = endTime.minusDays(9-i);
                times.add(dateTimeFormatter.format(start));
                //瞬时流量
                 Double avg = iotService.maxBySnAndCode(snCode,"0x0592",start,end);
                datas.add(avg==null?0:Double.parseDouble(decimalFormat.format(avg)));
                log.info("瞬时流量计算结果:{}", avg==null?0:Double.parseDouble(decimalFormat.format(avg)));
            });
            object.put("times", times);
            object.put("datas", datas);
            object.put("unit", unit);
            object.put("attribute", attribute);
            chartData.add(object);

            //日累积流量
            JSONArray times2 = new JSONArray();
            JSONArray datas2 = new JSONArray();
            JSONObject object2 = new JSONObject();
            String unit2 = "m³";
            String attribute2 = "日累积流量";
            IntStream.range(0,10).forEach(i->{
                log.info("日累积流量{}", i);
                LocalDateTime start = startTime.minusDays(9-i);
                log.info("start:{}", start);
                LocalDateTime end = endTime.minusDays(9-i);
                String date = dateTimeFormatter.format(start);
                times2.add(date);
                // 查累计流量
                LambdaQueryWrapper<OptDeviceMonitorAnalyseData> llWrapper = Wrappers.<OptDeviceMonitorAnalyseData>lambdaQuery()
                        .eq(OptDeviceMonitorAnalyseData::getDeviceCode, snCode)
                        .eq(OptDeviceMonitorAnalyseData::getCode, Constant.MonitorInfo.C_CC0001.getCode())
                        .eq(OptDeviceMonitorAnalyseData::getMonitorTime, date)
                        .orderByDesc(OptDeviceMonitorAnalyseData::getMonitorTime)
                        .last("LIMIT 1");
                OptDeviceMonitorAnalyseData llOne = optDeviceMonitorAnalyseDataService.getOne(llWrapper);
                if(llOne==null){
                    datas2.add(0);
                    log.info("日累积流量计算结果[llOne==null]{}", 0);
                }else{
                    BigDecimal bigDecimal = BigDecimal.valueOf(llOne.getCodeValue()).setScale(2, RoundingMode.HALF_DOWN);
                    datas2.add(bigDecimal.doubleValue());
                    log.info("日累积流量计算结果{}", bigDecimal.doubleValue());
                }

            });
            object2.put("times", times2);
            object2.put("datas", datas2);
            object2.put("unit", unit2);
            object2.put("attribute", attribute2);
            chartData.add(object2);
        }
        return AjaxResult.success(chartData);
    }
    private JSONArray getArray(JSONArray array, String deviceCode) {
        JSONArray result = new JSONArray();
        array.forEach(o -> {
            JSONObject object = (JSONObject)o;
            JSONObject data = new JSONObject();
            String timeSeries = object.getString("Timeseries");
            String sensorCode = timeSeries.substring(timeSeries.lastIndexOf(".")+1);
            for(Constant.MonitorInfo monitorInfo:Constant.MonitorInfo.values()){
                if(monitorInfo.getCode().equals(sensorCode)){
                    if("井盖倾角".equals(Constant.MonitorInfo.getInfoByCode(sensorCode).getName())){
                        data.put("name","井盖状态");
                        data.put("unit","/");
                        data.put("value",object.getString("Value"));
                        data.put("status",Double.parseDouble(object.getString("Value"))>30?"开启":"关闭");
                        data.put("time",object.getString("time"));
                    }else if("瞬时流量".equals(Constant.MonitorInfo.getInfoByCode(sensorCode).getName())){
                        data.put("name",Constant.MonitorInfo.getInfoByCode(sensorCode).getName());
                        data.put("unit",Constant.MonitorInfo.getInfoByCode(sensorCode).getUnit());
                        data.put("value",object.getString("Value"));
                        data.put("time",object.getString("time"));
                        if(Double.parseDouble(object.getString("Value"))<0.5){
                            data.put("status", "流速过缓");
                        }else {
                            data.put("status", "正常");
                        }
                    }else if("正向累积流量".equals(Constant.MonitorInfo.getInfoByCode(sensorCode).getName())){
                        data.put("name","日累计流量");
                        data.put("unit",Constant.MonitorInfo.getInfoByCode(sensorCode).getUnit());

                        // 昨天的日期
                        String yesterday = DateUtil.formatDate(DateUtil.offsetDay(new Date(), -1));
                        // 查昨日累计流量
                        LambdaQueryWrapper<OptDeviceMonitorAnalyseData> llWrapper = Wrappers.<OptDeviceMonitorAnalyseData>lambdaQuery()
                                .eq(OptDeviceMonitorAnalyseData::getDeviceCode, deviceCode)
                                .eq(OptDeviceMonitorAnalyseData::getCode, Constant.MonitorInfo.C_CC0001.getCode())
                                .eq(OptDeviceMonitorAnalyseData::getMonitorTime, yesterday)
                                .orderByDesc(OptDeviceMonitorAnalyseData::getMonitorTime)
                                .last("LIMIT 1");
                        OptDeviceMonitorAnalyseData llOne = optDeviceMonitorAnalyseDataService.getOne(llWrapper);
                        if (llOne == null) {
                            log.error("昨日流量为空");
                            return;
                        }
                        data.put("value",llOne.getCodeValue()+"");
                        data.put("time",object.getString("time"));
                    }else if("液位高度".equals(Constant.MonitorInfo.getInfoByCode(sensorCode).getName())){
                        data.put("name", Constant.MonitorInfo.getInfoByCode(sensorCode).getName());
                        data.put("unit",Constant.MonitorInfo.getInfoByCode(sensorCode).getUnit());
                        data.put("value",object.getString("Value"));
                        data.put("status","正常");
                        data.put("time",object.getString("time"));
                    } else  {
                        data.put("name",Constant.MonitorInfo.getInfoByCode(sensorCode).getName());
                        data.put("unit",Constant.MonitorInfo.getInfoByCode(sensorCode).getUnit());
                        data.put("value",object.getString("Value"));
                        data.put("time",object.getString("time"));
                    }

                    break;
                }
            }

            result.add(data);
        });
        return result;
    }

    /**
     * 查询设备管理列表以及最后回传时间
     */
    @ApiOperation("查询设备管理列表以及最后回传时间")
    @GetMapping("/listAndLastTime")
    public TableDataInfo<?> listAndLastTime(OptDeviceDto optDevice){
        startPage();
        List<OptDeviceDto> list = optDeviceService.selectOptDeviceListAndLastTime(optDevice);
        TableDataInfo dataTable = getDataTable(list);
        List<String> resultList = new ArrayList<>();
        list.forEach(optDeviceDto -> {
            resultList.add(Base64.getEncoder().encodeToString(JSONObject.toJSONString(optDeviceDto).getBytes(StandardCharsets.UTF_8)));
        });
        dataTable.setRows(resultList);
        return dataTable;
    }

    /**
     * 查询设备编码的重复数量
     */
    @ApiOperation("查询设备编码的重复数量")
    @GetMapping("/getDeviceCodeCount")
    public AjaxResult getDeviceCodeCount(@RequestParam String deviceCode, @RequestParam(required = false) Long id){
        return success(optDeviceService.getDeviceCodeCount(deviceCode, id));
    }

    /**
     * 查询真实设备编码的重复数量
     */
    @ApiOperation("查询真实设备编码的重复数量")
    @GetMapping("/getRealDeviceCodeCount")
    public AjaxResult getRealDeviceCodeCount(@RequestParam String realDeviceCode, @RequestParam(required = false) Long id){
        return success(optDeviceService.getRealDeviceCodeCount(realDeviceCode, id));
    }

    /**
     * 根据id查询设备详细信息
     */
    @ApiOperation("根据id查询设备详细信息")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id){
        return AjaxResult.success(optDeviceService.selectOptDeviceById(id));
    }

    /**
     * 根据id查询设备详细信息
     */
    @ApiOperation("根据id查询设备详细信息")
    @GetMapping(value = "/getDeviceAndRelation/{id}")
    public AjaxResult getDeviceAndRelation(@PathVariable("id") Long id){
        return AjaxResult.success(optDeviceService.getDeviceAndRelation(id));
    }

    /**
     * 新增设备信息
     */
    @ApiOperation("新增设备信息")
    @Log(title = "设备管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody @Validated OptDevice optDevice){
        return toAjax(optDeviceService.saveDevice(optDevice));
    }

    /**
     * 修改设备信息
     */
    @ApiOperation("修改设备信息")
    @Log(title = "设备管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody @Validated OptDevice optDevice){
        return toAjax(optDeviceService.updateDeviceById(optDevice));
    }

    /**
     * 新增设备关联关系
     */
    @ApiOperation("新增设备关联关系")
    @Log(title = "设备管理", businessType = BusinessType.INSERT)
    @PostMapping("/addDeviceAndRelation")
    public AjaxResult addDeviceAndRelation(@RequestBody @Validated OptDeviceAndRelation deviceAndRelation){
        return toAjax(optDeviceService.saveDeviceAndRelation(deviceAndRelation));
    }

    /**
     * 修改设备关联关系
     */
    @ApiOperation("修改设备关联关系")
    @Log(title = "设备管理", businessType = BusinessType.UPDATE)
    @PutMapping("/editDeviceAndRelation")
    public AjaxResult editDeviceAndRelation(@RequestBody @Validated OptDeviceAndRelation deviceAndRelation){
        return toAjax(optDeviceService.updateDeviceAndRelation(deviceAndRelation));
    }

    /**
     * 删除设备管理
     */
    @ApiOperation("删除设备管理")
    @Log(title = "设备管理", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids){
        return toAjax(optDeviceService.deleteDevice(Arrays.asList(ids)));
    }
    /**
     * 导出设备管理列表
     */
    @ApiOperation("导出设备管理列表")
    @Log(title = "设备管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, OptDeviceDto optDevice){
        List<OptDeviceDto> list = optDeviceService.selectOptDeviceList(optDevice);
        ExcelUtil<OptDeviceDto> util = new ExcelUtil<OptDeviceDto>(OptDeviceDto.class);
        util.exportExcel(response, list, "设备管理数据");
    }

    @GetMapping(value = "/quantity")
    public AjaxResult getQuantity(AlarmSearchInput inputs){
        return AjaxResult.success(optDeviceService.selectOptDeviceQuantity(inputs));
    }

    @GetMapping(value = "/alarmquantity")
    public AjaxResult getAlarmQuantity(AlarmSearchInput input){
        return AjaxResult.success(optDeviceService.selectOptDeviceAlarmQuantity(input));
    }

    /**
     * 查询河道监测相关设备
     * @param state 0液位，1流量（全部），2水质
     */
    @ApiOperation("河道监测设备")
    @GetMapping(value = "/getByDeviceType/{state}")
    public AjaxResult getByDeviceType(@PathVariable Integer state){
        return AjaxResult.success(optDeviceService.getByDeviceType(state,null));
    }

    /**
     * 根据设备类型查询设备
     */
    @ApiOperation("根据设备类型查询设备")
    @GetMapping(value = "/getByDeviceTypes")
    public AjaxResult getByDeviceTypes(OptDeviceDto optDeviceDto){
        return AjaxResult.success(optDeviceService.getByDeviceTypes(optDeviceDto));
    }

    /**
     * 获取街道的报警数量
     */
    @ApiOperation("获取街道的报警数量")
    @GetMapping(value = "/getStreetAlarm")
    public AjaxResult getStreetAlarm(AlarmSearchInput inputs){
        return AjaxResult.success(optDeviceService.selectStreetAlarm(inputs));
    }

    /**
     * 获取街道下子项的报警数量
     */
    @ApiOperation("获取街道下子项的报警数量")
    @GetMapping(value = "/getStreetSubAlarm")
    public AjaxResult getStreetSubAlarm(AlarmSearchInput inputs){
        return AjaxResult.success(optDeviceService.selectStreetSubAlarm(inputs));
    }

    /**
     * 获取所以设备，按照设备类型分组返回
     */
    @ApiOperation("获取所以设备，按照设备类型分组返回")
    @GetMapping(value = "/getAll")
    public AjaxResult getAll(){
        return AjaxResult.success(optDeviceService.getAll(0));
    }

    /**
     * 获取所以设备，按照设备类型分组返回(排除未安装)
     */
    @ApiOperation("获取所以设备，按照设备类型分组返回(排除未安装)")
    @GetMapping(value = "/getAllInstall")
    public AjaxResult getAllInstall(){
        return AjaxResult.success(optDeviceService.getAll(1));
    }

    /**
     * 对listAndLastTime接口重新封装
     */
    @ApiOperation("设备在线/离线")
    @GetMapping("/onOffLine")
    public AjaxResult selectOnOffLine(OnOffLineDto dto){
        return AjaxResult.success(optDeviceService.selectOnOffLine(dto));
    }

    /**
     * 碧水指数-畅水因子-总设备详情
     */
    @ApiOperation("碧水指数-畅水因子-总设备详情")
    @GetMapping("/backstageDeviceSum/{state}")
    public AjaxResult backstageDeviceSum(@PathVariable("state") Integer state ,@RequestParam String areaName){
        return success(optDeviceService.backstageDeviceSum(state,areaName));
    }
    @GetMapping("getDeviceCount")
    public AjaxResult getDeviceCount(){
        long totalCount = optDeviceService.count();
        long offLineCount = 0;
        List<OptDeviceDto> list = optDeviceService.selectOptDeviceListAndLastTime(null);
        for (OptDeviceDto optDeviceDto : list) {
            if(optDeviceDto.getDeviceLastTime()==null || optDeviceDto.getDeviceLastTime().getTime()<System.currentTimeMillis()- 48*60*60*1000){
                offLineCount++;
            }
        }
        JSONObject object = new JSONObject();
        object.put("totalCount", totalCount);
        object.put("offLineCount", offLineCount);
        return AjaxResult.success(object);
    }
}
